package com.zjxf.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.zjxf.base.bean.po.CmsNews;
import com.zjxf.base.bean.po.UmsStoreSeller;
import com.zjxf.base.bean.ro.RoCmsNews;
import com.zjxf.base.bean.sort.SortDto;
import com.zjxf.base.bean.sort.SortUtils;
import com.zjxf.base.bean.vo.VoCmsNews;
import com.zjxf.base.common.OperationException;
import com.zjxf.base.common.SysConst;
import com.zjxf.repository.CmsNewsRepository;
import com.zjxf.service.CmsNewsService;
import com.zjxf.utils.Conversion;
import com.zjxf.utils.DynamicSpecifications;
import com.zjxf.utils.PageUtils;
import com.zjxf.utils.SearchFilter;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 新闻
 *
 * @author ZhangWei
 * @date 2021/4/6/006 10:52
 */
@Service
@AllArgsConstructor
@Transactional(rollbackOn = RuntimeException.class)
public class CmsNewsServiceImpl implements CmsNewsService {

    private final CmsNewsRepository cmsNewsRepository;

    public Optional<CmsNews> findById(Long id) {
        return cmsNewsRepository.findByIdAndDeleteState(id, SysConst.DeleteState.UN_DELETE_STATE.getCode());
    }

    @Override
    public void addOrUpdate(VoCmsNews.addOrUpdate vo, UmsStoreSeller umsStoreSeller) throws OperationException {

        Optional<CmsNews> optionalCmsNews = findById(vo.getId());
        CmsNews cmsNews;
        if (optionalCmsNews.isPresent()) {
            cmsNews = optionalCmsNews.get();
            cmsNews = Conversion.voTurnPo(vo, cmsNews);
            cmsNews.setUpdateTime(LocalDateTime.now());
            cmsNews.setPublisherId(umsStoreSeller.getId());
        } else {
            cmsNews = new CmsNews();
            cmsNews = Conversion.voTurnPo(vo, cmsNews);
            cmsNews.setStoreId(umsStoreSeller.getStoreId());
            cmsNews.setPublisherId(umsStoreSeller.getId());
            cmsNews.setVerifyStatus(SysConst.VerifyStatus.IN_REVIEW.getCode());
            cmsNewsRepository.save(cmsNews);
        }
    }

    @Override
    public void delete(Long id) throws OperationException {
        CmsNews cmsNews = findById(id).orElseThrow(() -> new OperationException(SysConst.DATA_NOT_FOND));
        cmsNews.setDeleteState(SysConst.DeleteState.DELETE_STATE.getCode());
        cmsNewsRepository.save(cmsNews);
    }

    @Override
    public CmsNews getEntity(Long id) throws OperationException {
        return findById(id).orElseThrow(() -> new OperationException(SysConst.DATA_NOT_FOND));
    }

    @Override
    public RoCmsNews.Details getEntityRo(CmsNews cmsNews) {
        return Conversion.poTurnRo(cmsNews, new RoCmsNews.Details());
    }

    @Override
    public Page<CmsNews> page(VoCmsNews.filter filter, UmsStoreSeller umsStoreSeller) {
        //TODO 此处始终无法解决 通过提取 List<SearchFilter> searchFilters无法存入IOC
        List<SearchFilter> searchFilters = new ArrayList<>();
        searchFilters.add(new SearchFilter("storeId", SearchFilter.Operator.EQ, umsStoreSeller.getStoreId()));
        if (StringUtils.isNotBlank(filter.getKeywords())) {
            searchFilters.add(new SearchFilter("title", SearchFilter.Operator.LIKE, filter.getKeywords()));
        }
        if (filter.getShowState() != null) {
            searchFilters.add(new SearchFilter("showState", SearchFilter.Operator.EQ, filter.getShowState()));
        }
        if (filter.getVerifyStatus() != null) {
            searchFilters.add(new SearchFilter("verifyStatus", SearchFilter.Operator.EQ, filter.getVerifyStatus()));
        }
        if (filter.getType() != null) {
            searchFilters.add(new SearchFilter("type", SearchFilter.Operator.EQ, filter.getType()));
        }
        return getCmsNews(searchFilters, filter.getStartTime(), filter.getEndTime(), filter.getPageNum(), filter.getPageSize());
    }

    @Override
    public Page<CmsNews> appPage(VoCmsNews.appFilter filter) {
        List<SearchFilter> searchFilters = new ArrayList<>();
        if (filter.getShowState() != null) {
            searchFilters.add(new SearchFilter("showState", SearchFilter.Operator.EQ, filter.getShowState()));
        }
        if (filter.getType() != null) {
            searchFilters.add(new SearchFilter("type", SearchFilter.Operator.EQ, filter.getType()));
        }
        return getCmsNews(searchFilters, filter.getStartTime(), filter.getEndTime(), filter.getPageNum(), filter.getPageSize());
    }

    private Page<CmsNews> getCmsNews(List<SearchFilter> searchFilters, String startTime, String endTime, Integer pageNum, Integer pageSize) {
        Specification<CmsNews> specification = DynamicSpecifications.bySearchFilterByBasic(searchFilters, startTime, endTime);
        SortUtils.basicSort(
                new SortDto(SysConst.SortOrder.DESC.getCode(), "showState"),
                new SortDto(SysConst.SortOrder.DESC.getCode(), "type"),
                new SortDto(SysConst.SortOrder.DESC.getCode(), "createTime")
        );
        return cmsNewsRepository.findAll(specification, PageUtils.buildPageRequest(pageNum, pageSize));
    }

    @Override
    public JSONObject pageRo(Page<CmsNews> cmsNewsPage) {
        List<CmsNews> pageList = cmsNewsPage.getContent();
        List<RoCmsNews.Page> roList = pageList.stream().map(item -> Conversion.voTurnPo(item, new RoCmsNews.Page())).collect(Collectors.toList());
        return PageUtils.page(cmsNewsPage, roList);
    }

    @Override
    public void switchShow(VoCmsNews.SwitchShow vo) throws OperationException {
        CmsNews cmsNews = findById(vo.getId()).orElseThrow(() -> new OperationException(SysConst.DATA_NOT_FOND));
        cmsNews.setShowState(vo.getShowState());
        cmsNewsRepository.save(cmsNews);
    }
}
